package cn.com.stary1993.kite.captcha.config;


import cloud.tianai.captcha.generator.ImageCaptchaGenerator;
import cloud.tianai.captcha.generator.ImageTransform;
import cloud.tianai.captcha.generator.impl.CacheImageCaptchaGenerator;
import cloud.tianai.captcha.generator.impl.transform.Base64ImageTransform;
import cloud.tianai.captcha.resource.ImageCaptchaResourceManager;
import cloud.tianai.captcha.resource.ResourceStore;
import cloud.tianai.captcha.resource.impl.DefaultImageCaptchaResourceManager;
import cloud.tianai.captcha.validator.ImageCaptchaValidator;
import cloud.tianai.captcha.validator.impl.BasicCaptchaTrackValidator;
import cn.com.stary1993.kite.captcha.store.CacheStore;
import cn.com.stary1993.kite.captcha.support.behavior.*;
import cn.com.stary1993.kite.captcha.support.behavior.secondary.BehaviorImageCaptchaSecondaryVerification;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Role;

/**
 * @author stary1993
 * <p>
 * 行为验证码配置类
 */
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(
        prefix = CaptchaProperties.PREFIX + "." + CaptchaProperties.BEHAVIOR,
        name = "enabled",
        havingValue = "true")
public class BehaviorImageCaptchaAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean
    public ResourceStore resourceStore(CaptchaProperties prop) {
        return new BehaviorImageCaptchaResourceStore(prop.getBehavior());
    }

    @Bean
    @ConditionalOnMissingBean
    public ImageTransform imageTransform() {
        return new Base64ImageTransform();
    }

    @Bean
    @ConditionalOnMissingBean
    public ImageCaptchaResourceManager imageCaptchaResourceManager(ResourceStore resourceStore) {
        return new DefaultImageCaptchaResourceManager(resourceStore);
    }

    @Bean
    @ConditionalOnMissingBean
    public ImageCaptchaGenerator imageCaptchaTemplate(CaptchaProperties prop,
                                                      ImageCaptchaResourceManager captchaResourceManager, ImageTransform imageTransform,
                                                      BeanFactory beanFactory) {
        // 构建多验证码生成器
        ImageCaptchaGenerator captchaGenerator = new SpringMultiBehaviorImageCaptchaGenerator(
                captchaResourceManager, imageTransform, beanFactory);
        BehaviorImageCaptchaProperties.CaptchaCacheProperties cache = prop.getBehavior().getCache();
        if (cache != null && cache.getEnabled() && cache.getCacheSize() > 0) {
            // 增加缓存处理
            captchaGenerator = new CacheImageCaptchaGenerator(captchaGenerator, cache.getCacheSize(),
                    cache.getWaitTime(), cache.getPeriod());
        }
        // 初始化
        captchaGenerator.init(false);
        return captchaGenerator;
    }

    @Bean
    @ConditionalOnMissingBean
    public ImageCaptchaValidator imageCaptchaValidator(CaptchaProperties prop) {
        return new BasicCaptchaTrackValidator(prop.getBehavior().getDefaultTolerant());
    }

    @Bean
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    @ConditionalOnMissingBean
    public BehaviorImageCaptchaCacheTemplateListener captchaTemplateListener() {
        return new BehaviorImageCaptchaCacheTemplateListener();
    }

    @Bean
    @ConditionalOnMissingBean
    public BehaviorImageCaptcha behaviorImageCaptcha(ImageCaptchaGenerator captchaGenerator,
                                                     ImageCaptchaValidator imageCaptchaValidator, CacheStore cacheStore, CaptchaProperties prop) {
        BehaviorImageCaptcha target = new DefaultBehaviorImageCaptcha(captchaGenerator, imageCaptchaValidator,
                cacheStore, prop.getBehavior());
        if (prop.getBehavior().getSecondary() != null
                && Boolean.TRUE.equals(prop.getBehavior().getSecondary().getEnabled())) {
            target = new BehaviorImageCaptchaSecondaryVerification(target, prop.getBehavior().getSecondary());
        }
        return target;
    }
}
